package cn.tesla_iot.chat.video.monitor.call;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.util.Log;
import android.widget.FrameLayout;
import android.widget.Toast;

import cn.iotnova.rtc.WebrtcPeer;
import cn.tesla_iot.chat.video.monitor.R;
import cn.tools.JnaTools;
import cn.tools.JniTools;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;

import org.json.JSONException;
import org.json.JSONObject;
import org.webrtc.EglBase;
import org.webrtc.PeerConnection;

import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
//https://github.com/JumpingYang001/webrtc
//https://www.jianshu.com/p/94d6defc8e27

public class VideoCallActivity extends AppCompatActivity {
/*
    static {
        //System.loadLibrary("bcast");
        System.loadLibrary("jnidispatch");
    }
 */

    /**
     * set true if you want to record movie using MediaSurfaceEncoder
     * (writing frame data into Surface camera from MediaCodec
     *  by almost same way as USBCameratest2)
     * set false if you want to record movie using MediaVideoEncoder
     */
    private static final boolean USE_SURFACE_ENCODER = false;

    /**
     * preview resolution(width)
     * if your camera does not support specific resolution and mode,
     * {@link UVCCamera#setPreviewSize(int, int, int)} throw exception
     */
    private static final int PREVIEW_WIDTH = 640;
    /**
     * preview resolution(height)
     * if your camera does not support specific resolution and mode,
     * {@link UVCCamera#setPreviewSize(int, int, int)} throw exception
     */
    private static final int PREVIEW_HEIGHT = 480;
    /**
     * preview mode
     * if your camera does not support specific resolution and mode,
     * {@link UVCCamera#setPreviewSize(int, int, int)} throw exception
     * 0:YUYV, other:MJPEG
     */
    private static final int PREVIEW_MODE = 1;

    private static final String mCurrentCallRoom = "<SOME_ROOM_NAME>";
    private static final int CAMERA_PERMISSION_REQUEST_CODE = 5152;
    private static final String TAG = "VideoCallActivity";
    private EglBase rootEglBase;
    private List<PeerConnection.IceServer> peerIceServers = new ArrayList<>();
    private boolean isSpeakerOn;
    private FloatingActionButton mSpeakerButton;

    public InetAddress intToInet(int ipAddress) {
        byte[] bytes = BigInteger.valueOf(ipAddress).toByteArray();
        InetAddress address = null;
        try {
            address = InetAddress.getByAddress(bytes);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        return address;
    }

    public byte[] toIPByteArray(int addr){
        return new byte[]{(byte)addr,(byte)(addr>>>8),(byte)(addr>>>16),(byte)(addr>>>24)};
    }

    public InetAddress toInetAddress(int addr){
        try {
            return InetAddress.getByAddress(toIPByteArray(addr));
        } catch (UnknownHostException e) {
            //should never happen
            return null;
        }
    }

    public String getSSID() {
        WifiManager wm = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
        if (wm != null) {
            WifiInfo winfo = wm.getConnectionInfo();
            if (winfo != null) {
                String s = winfo.getSSID();
                if (s.length() > 2 && s.charAt(0) == '"' && s.charAt(s.length() - 1) == '"') {
                    return s.substring(1, s.length() - 1);
                }
            }
        }
        return "";
    }

    public InetAddress getWifiIp() {
        WifiManager wifiMgr = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if (isWifiEnabled()) {
            int ipAsInt = wifiMgr.getConnectionInfo().getIpAddress();
            if (ipAsInt == 0) {
                return null;
            } else {
                return toInetAddress(ipAsInt);   //intToInet(ipAsInt);
            }
        } else {
            return null;
        }
    }



    public int getWifiIpInt() {
        WifiManager wifiMgr = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if (isWifiEnabled()) {
            int ipAsInt = wifiMgr.getConnectionInfo().getIpAddress();
            if (ipAsInt == 0) {
                return 0;
            } else {
                return ipAsInt;   //intToInet(ipAsInt);
            }
        } else {
            return 0;
        }
    }

    public boolean isWifiEnabled() {
        WifiManager wifiMgr = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if (wifiMgr.getWifiState() == WifiManager.WIFI_STATE_ENABLED) {
            ConnectivityManager connManager = (ConnectivityManager) getApplicationContext()
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo wifiInfo = connManager
                    .getNetworkInfo(ConnectivityManager.TYPE_WIFI);
            return wifiInfo.isConnected();
        } else {
            return false;
        }
    }

    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 1: {
                    Toast.makeText(VideoCallActivity.this, msg.obj.toString(), Toast.LENGTH_SHORT).show();

                    FloatingActionButton hangup = (FloatingActionButton) findViewById(R.id.end_call_button);
                    //hangup.setOnClickListener(this);
                    hangup.setOnClickListener((v) -> {
                        runOnUiThread(() -> {
                            hangup();
                        });
                    });
                }
                    break;
                case 2:
                    startWebRTC();
                    break;
                case 3: {
                    Toast.makeText(VideoCallActivity.this, "找不到设备,请重试", Toast.LENGTH_SHORT).show();
                    /*
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    finish();
                     */

                    FloatingActionButton hangup = (FloatingActionButton) findViewById(R.id.end_call_button);
                    //hangup.setOnClickListener(this);
                    hangup.setOnClickListener((v) -> {
                        runOnUiThread(() -> {
                            hangup();
                        });
                    });
                }
                    break;
            }
        }
    };

    WebrtcPeer peer;
    FrameLayout frameLayoutMain;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video_call);

        if (true) {

            rootEglBase = EglBase.create();
            initStuff();
            frameLayoutMain = findViewById(R.id.activity_main);
            peer = new WebrtcPeer(VideoCallActivity.this);
            peer.startPeer("phone", 1, rootEglBase, frameLayoutMain, R.id.local_gl_surface_view, R.id.remote_gl_surface_view, getApplicationContext(), peerIceServers);

            /*
            new Thread(new Runnable() {
                @Override
                public void run() {
                    peer.ClientSendData(connId, 1, "1");
                }
            })
             */
            return;
        }

        int ip = getWifiIpInt();

        if (ip != 0) {
            Toast.makeText(this, intToInet(ip).getHostAddress(), Toast.LENGTH_SHORT).show();

            if (false) {
                JnaTools jniTools = JnaTools.INSTANCE;

                //https://www.jianshu.com/p/234132692041
                if (jniTools != null) {
                    Pointer pointer = new Memory(80);
                    int ret = jniTools.getdevip(ip, pointer);

                    if (ret > 0) {
                        //获取字节数组
                        byte[] byteArray = pointer.getByteArray(0, 40);

                    /*
                    int slen = 0;
                    for (slen = 0; slen < 40; slen++) {
                        if (byteArray[slen] == 0)
                            break;
                    }

                     */
                        //转化成字符
                        //System.out.println(new String(byteArray,"GB2312"));
                        String desip = new String(byteArray, 0, ret);
                        if (!desip.equals("")) {
                            try {
                                JSONObject obj = new JSONObject(desip);
                                MainActivity.sPeerIP = obj.getString("ip");
                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                            Toast.makeText(this, desip, Toast.LENGTH_SHORT).show();
                        }

                    } else {
                        Toast.makeText(this, "error", Toast.LENGTH_SHORT).show();
                    }
                } else {
                    Toast.makeText(this, "jniTools is null", Toast.LENGTH_SHORT).show();
                }
            } else {

                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        int t = 3;
                        String sip = null;
                        while (t-- > 0) {
                            try {
                                String dstip = JniTools.getdevip(ip);
                                if (!dstip.equals("")) {
                                    JSONObject obj;
                                    try {
                                        obj = new JSONObject(dstip);
                                        sip = obj.getString("ip");

                                        if (sip != null && !sip.equals("")) {
                                            MainActivity.sPeerIP = sip;
                                        }
                                        Message msg = new Message();
                                        msg.what = 2;
                                        handler.sendMessage(msg);

                                    } catch (JSONException e) {
                                        e.printStackTrace();
                                    }
                                    if (sip == null || sip.equals("")) {
                                        continue;
                                    }

                                    //Toast.makeText(this, dstip, Toast.LENGTH_SHORT).show();
                                    Message msg = new Message();
                                    msg.what = 1;
                                    msg.obj = dstip;
                                    handler.sendMessage(msg);
                                } else {
                                    Message msg = new Message();
                                    msg.what = 2;
                                    handler.sendMessage(msg);
                                }
                                break;
                            } catch (Exception e) {
                                Message msg = new Message();
                                msg.what = 1;
                                msg.obj = e.getMessage();
                                handler.sendMessage(msg);
                            }
                        }
                        if ( t == 0) {
                            Message msg = new Message();
                            msg.what = 3;
                            handler.sendMessage(msg);
                        }
                    }
                }).start();
            }
        }
        //startWebRTC();
    }

    void startWebRTC() {

        //requestCameraPermission();
        initStuff();

        FloatingActionButton hangup = (FloatingActionButton) findViewById(R.id.end_call_button);
        //hangup.setOnClickListener(this);
        hangup.setOnClickListener((v)->{
            runOnUiThread(()->{
                hangup();
            });
        });

        AudioManager audioManager = ((AudioManager) getSystemService(AUDIO_SERVICE));
        isSpeakerOn = audioManager.isSpeakerphoneOn();

        /*
        mSpeakerButton = (FloatingActionButton) findViewById(R.id.speaker_change);
        if (isSpeakerOn) {
            mSpeakerButton.setImageResource(R.drawable.ic_speaker_phone);
        } else {
            mSpeakerButton.setImageResource(R.drawable.ic_speaker);
            setAudioOutput();
        }
        //mSpeakerButton.setOnClickListener(this);
        mSpeakerButton.setOnClickListener((v)->{
            runOnUiThread(()->{
                mSignallingClient.sendMessage("{\"type\":\"cmd\",\"name\":\"car\"}");
            });
        });
         */
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        peer.close();
        rootEglBase.releaseSurface();
    }


    private void getIceServers() {
        /*
        PeerConnection.IceServer peerIceServer = PeerConnection.IceServer.builder("stun:stun.l.google.com:19302").createIceServer();

        PeerConnection.IceServer peerIceServerStun = PeerConnection.IceServer.builder("stun:www.dmiot.top:3478?transport=udp")
                .setUsername("ddssingsong")
                .setPassword("123456")
                .createIceServer();

        PeerConnection.IceServer peerIceServerTurn = PeerConnection.IceServer.builder("turn:www.dmiot.top:3478?transport=udp")
                .setUsername("ddssingsong")
                .setPassword("123456")
                .createIceServer();

        PeerConnection.IceServer peerIceServerTurnTcp = PeerConnection.IceServer.builder("turn:www.dmiot.top:3478?transport=tcp")
                .setUsername("ddssingsong")
                .setPassword("123456")
                .createIceServer();

        peerIceServers.add(peerIceServer);
        peerIceServers.add(peerIceServerStun);
        peerIceServers.add(peerIceServerTurn);
        peerIceServers.add(peerIceServerTurnTcp);
         */
        //PeerConnection.IceServer peerIceServer = PeerConnection.IceServer.builder("stun:"+MainActivity.sPeerIP+":3478").createIceServer();
        PeerConnection.IceServer peerIceServer = PeerConnection.IceServer.builder("stun:stun.l.google.com:19302").createIceServer();
        peerIceServers.add(peerIceServer);

    }

    //boolean peerConnected = false;


    private void setAudioOutput() {
        AudioManager audioManager = ((AudioManager) getSystemService(AUDIO_SERVICE));
        if (isSpeakerOn) {
            isSpeakerOn = false;
            audioManager.setMode(AudioManager.MODE_NORMAL);
            mSpeakerButton.setImageResource(R.drawable.ic_speaker);
        } else {
            isSpeakerOn = true;
            audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
            mSpeakerButton.setImageResource(R.drawable.ic_speaker_phone);
        }
        audioManager.setSpeakerphoneOn(isSpeakerOn);
    }


    @Override
    protected void onStart() {
        super.onStart();

    }



    @Override
    protected void onStop() {
        super.onStop();
    }

    /**
     * Received local ice candidate. Send it to remote peer through signalling for negotiation
     */
    /*
    public void onIceCandidateReceived(IceCandidate iceCandidate) {
    }
     */

    public void onRemoteHangUp(String msg) {
        Log.d("onRemoteHangUp", "Remote Peer hanged up");
        runOnUiThread(() -> hangup());
    }

    private void hangup() {
        try {
            //updateVideoViews(false);
            android.os.Process.killProcess(android.os.Process.myPid());
            finish();
        } catch (Exception e) {
            android.os.Process.killProcess(android.os.Process.myPid());
            finish();
            e.printStackTrace();
        }

    }


    /**
     * Util Methods
     */
    public int dpToPx(int dp) {
        DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
        return Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
    }


    private void initStuff() {
        //initViews();
        //initVideos();

        getIceServers();
        //start();
    }


    private void requestCameraPermission() {
        int hasCameraPermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
        int hasAudioPermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO);
        if (hasCameraPermission != PackageManager.PERMISSION_GRANTED || hasAudioPermission != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO}, CAMERA_PERMISSION_REQUEST_CODE);
        } else {
            initStuff();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == CAMERA_PERMISSION_REQUEST_CODE) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                initStuff();
            } else {
                Toast.makeText(this, R.string.camera_permission_fail, Toast.LENGTH_SHORT).show();
                android.os.Process.killProcess(android.os.Process.myPid());
                finish();
            }
        }
    }


    /////////////////////////////////////////////////////////////////////////////

    //============================需要接收的=====================================
}
